package com.aleyn.router.util

import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.util.Log
import java.lang.reflect.InvocationTargetException

/**
 * @author: Aleyn
 * @date: 2023/6/9 11:35
 */

/**
 * 通过反射获取 Application Context。
 * 这是一种无需外部传入 Context 即可在库内部获取全局上下文的方式。
 * 它首先尝试获取 ActivityThread 实例，然后通过该实例获取 Application 对象。
 *
 * @return 返回应用的 Application Context，如果获取失败则返回 null。
 */
@SuppressLint("PrivateApi")
internal fun getApplicationByReflect(): Context? {
    try {
        val activityThreadClass = Class.forName("android.app.ActivityThread")
        val thread = getActivityThread()
        val app = activityThreadClass.getMethod("getApplication").invoke(thread) ?: return null
        return (app as Application).applicationContext
    } catch (e: InvocationTargetException) {
        e.printStackTrace()
    } catch (e: NoSuchMethodException) {
        e.printStackTrace()
    } catch (e: IllegalAccessException) {
        e.printStackTrace()
    } catch (e: ClassNotFoundException) {
        e.printStackTrace()
    }
    return null
}

/**
 * 获取当前的 ActivityThread 实例。
 * 尝试两种方式：首先通过静态字段 `sCurrentActivityThread` 获取，如果失败，则尝试调用静态方法 `currentActivityThread()`。
 *
 * @return ActivityThread 实例，如果失败则返回 null。
 */
private fun getActivityThread(): Any? {
    return getActivityThreadInActivityThreadStaticField()
        ?: getActivityThreadInActivityThreadStaticMethod()
}

/**
 * 通过反射访问 `android.app.ActivityThread` 类的静态字段 `sCurrentActivityThread` 来获取 ActivityThread 实例。
 */
@SuppressLint("PrivateApi", "DiscouragedPrivateApi")
private fun getActivityThreadInActivityThreadStaticField(): Any? {
    return try {
        val activityThreadClass = Class.forName("android.app.ActivityThread")
        val sCurrentActivityThreadField =
            activityThreadClass.getDeclaredField("sCurrentActivityThread")
        sCurrentActivityThreadField.isAccessible = true
        sCurrentActivityThreadField[null]
    } catch (e: Exception) {
        Log.e(
            "UtilsActivityLifecycle",
            "getActivityThreadInActivityThreadStaticField: " + e.message
        )
        null
    }
}

/**
 * 通过反射调用 `android.app.ActivityThread` 类的静态方法 `currentActivityThread()` 来获取 ActivityThread 实例。
 */
@SuppressLint("PrivateApi")
private fun getActivityThreadInActivityThreadStaticMethod(): Any? {
    return try {
        val activityThreadClass = Class.forName("android.app.ActivityThread")
        activityThreadClass.getMethod("currentActivityThread").invoke(null)
    } catch (e: java.lang.Exception) {
        Log.e(
            "UtilsActivityLifecycle",
            "getActivityThreadInActivityThreadStaticMethod: " + e.message
        )
        null
    }
}